<!--
 * Copyright © 2022 XXXXXXXXX
 * @Author: zhangxiang
 * @Date: 2022-08-29 16:03:55
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-09-21 15:19:17
 * @Description:
 *
-->

<template>
  <div id="deployment-main" class="deployment-ctn">
    <template v-if="!deploySuccess">
      <el-result icon="error" sub-title="启动部署失败，请重新启动">
        <template slot="extra">
          <el-button
            type="primary"
            size="medium"
            @click="restartClick"
          >重新启动部署</el-button>
        </template>
      </el-result>
    </template>
    <template v-else>
      <ServiceDeploymentV2
        v-for="(item, index) in microServices"
        :key="index"
        :micro-service="item"
        :stage-info="allStageInfo[item.svcId]"
        @retry-success="retrySuccessCallback"
      />
      <!-- 步骤按钮 -->
      <el-row type="flex" justify="end" style="margin-top: 30px">
        <el-button
          class="common-btn"
          type="primary"
          size="medium"
          :disabled="!complete"
          @click="completeClick"
        >完成</el-button>
      </el-row>
    </template>
  </div>
</template>

<script>
import { deployMicroService, getDeployStageInfo } from '@/api/cnap/app-service'
import ServiceDeploymentV2 from '../../components/ServiceDeploymentV2.vue'
import { Loading } from 'element-ui'
import {
  DEPLOY_STAGE_STEP_NUMS,
  DEPLOY_STAGE_STEP_NUMS_GPU,
  GPU_BUSINESS_SCENE,
  DEPLOY_STAGE_TITLES,
  DEPLOY_STAGE_DEFAULT_INFO
} from '@/utils/cnap/constant'

const POLLING_INTERVAL = 1000

/**
 * @description: 获取默认数据
 * @return {*}
 */
const getDefaultStageInfo = () => {
  return DEPLOY_STAGE_DEFAULT_INFO
}

export default {
  name: 'DeploymentV2',
  components: {
    ServiceDeploymentV2
  },
  props: {
    // 微服务
    microServices: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      allStageInfo: {}, // 微服务阶段信息
      timerPolling: null, // 轮询timer
      complete: false, // 微服务部署完成
      deploySuccess: true, // 部署是否成功
      loadingInstance: null // loading
    }
  },
  computed: {},
  destroyed() {
    if (this.timerPolling) {
      clearTimeout(this.timerPolling)
      this.timerPolling = null
    }
  },
  created() {
    this.initData()
  },
  methods: {
    /**
     * @description: 是GPU
     * @param {*} scheduleStrategy
     * @return {*}
     */
    isGPU(scheduleStrategy) {
      return (
        scheduleStrategy &&
        scheduleStrategy.businessScene &&
        scheduleStrategy.businessScene.svcType === GPU_BUSINESS_SCENE
      )
    },
    /**
     * @description: 重试回调
     * @param {*} svcId
     * @return {*}
     */
    retrySuccessCallback(svcId) {
      if (this.timerPolling) {
        // 取消原来的轮询
        clearTimeout(this.timerPolling)
        this.timerPolling = null
      }
      // 获取信息
      this.pollingStageInfo()
    },
    /**
     * @description: 处理部署信息
     * @param {*} data
     * @return {*}
     */
    handleStageInfo(data) {
      let complete = true // 全部微服务完成
      const allStageInfo = {}
      // 循环微服务
      for (const microService of this.microServices) {
        const isGPU = this.isGPU(microService.scheduleStrategy) // 是否GPU场景
        const stageStepNums = isGPU
          ? DEPLOY_STAGE_STEP_NUMS_GPU
          : DEPLOY_STAGE_STEP_NUMS // 阶段数
        // 查找相应微服务的部署信息
        const stageInfo = data.find((item) => {
          return item.svcId === microService.svcId
        })
        // 存在相应微服务的部署信息
        if (stageInfo) {
          allStageInfo[microService.svcId] = {}
          let svcSuccess = true // 微服务是否部署成功
          let svcError = false // 微服务是否部署失败
          const stageKes = [
            'firstStages',
            'secondStages',
            'thirdStages',
            'fourthStages'
          ]
          let currentStage = 1
          stageKes.forEach((key, index) => {
            let stageStatus = 0 // 0-未部署 1-部署中 2-部署失败 3-部署成功
            if (Array.isArray(stageInfo[key]) && stageInfo[key].length > 0) {
              stageStatus = 1
              const isError = stageInfo[key].some((item) => {
                return !item.success // 阶段的步骤信息存在不成功 则这个阶段不成功
              })
              if (isError) {
                stageStatus = 2
              }
              if (stageInfo[key].length === stageStepNums[index]) {
                const isSuccess = stageInfo[key].every((item) => {
                  return item.success // 阶段的步骤信息都成功 则这个阶段成功
                })
                if (isSuccess) {
                  stageStatus = 3
                }
              }
            }
            // 判断当前阶段
            if (stageStatus === 1) {
              currentStage = index + 1
            } else if (stageStatus === 2) {
              currentStage = index + 1
            } else if (stageStatus === 3) {
              currentStage = Math.min(index + 2, 4)
            }
            allStageInfo[microService.svcId][key] = {
              title: DEPLOY_STAGE_TITLES[index],
              stageStatus: stageStatus, // 阶段部署状态
              stepTotal: stageStepNums[index], // 阶段步骤总数
              steps: stageInfo[key] || [] // 阶段步骤详细信息
            }
            // 每个阶段都需要成功 微服务部署才成功
            svcSuccess = svcSuccess && stageStatus === 3
            // 有一个阶段成功 微服务部署都算失败
            svcError = svcError || stageStatus === 2
          })
          // 更新当前阶段
          allStageInfo[microService.svcId]['currentStage'] = currentStage
          // 当前阶段刚开始时，无法判断，通过currentStage判断补全状态
          if (
            allStageInfo[microService.svcId][stageKes[currentStage - 1]]
              .stageStatus === 0
          ) {
            allStageInfo[microService.svcId][
              stageKes[currentStage - 1]
            ].stageStatus = 1
          }
          // 设置微服务部署状态
          allStageInfo[microService.svcId]['svcStatus'] = svcError
            ? 2
            : svcSuccess
              ? 3
              : 1
          // 每个微服务都部署成功 才算结束
          complete = complete && svcSuccess
        } else {
          allStageInfo[microService.svcId] = getDefaultStageInfo()
          complete = complete && false
        }
      }
      this.allStageInfo = allStageInfo
      this.complete = complete
      if (this.complete) {
        // 完成
        if (this.timerPolling) {
          clearTimeout(this.timerPolling)
          this.timerPolling = null
        }
      } else {
        // 未完成
        this.timerPolling = setTimeout(() => {
          this.pollingStageInfo()
        }, POLLING_INTERVAL)
      }
    },
    /**
     * @description: 轮询获取阶段信息
     * @return {*}
     */
    pollingStageInfo() {
      const appId = this.microServices[0].appId // 应用id
      // 请求接口
      getDeployStageInfo(appId)
        .then((res) => {
          if (Array.isArray(res.data)) {
            // 处理部署信息
            this.handleStageInfo(res.data)
          } else {
            // 数据异常 继续轮询
            this.timerPolling = setTimeout(() => {
              this.pollingStageInfo()
            }, POLLING_INTERVAL)
          }
        })
        .catch((err) => {
          console.log(err)
        })
    },
    /**
     * @description: 重新启动部署
     * @return {*}
     */
    restartClick() {
      this.deployMicroServices()
    },
    /**
     * @description: 部署微服务
     * @return {*}
     */
    deployMicroServices() {
      // 展示loading
      this.loadingInstance = Loading.service({
        target: '#step-main',
        fullscreen: false,
        text: '启动部署中...'
      })
      const params = []
      for (const item of this.microServices) {
        if (item.status === '0') {
          // 初始状态的微服务
          params.push(item.svcId)
        }
      }
      deployMicroService(params)
        .then((res) => {
          // 部署成功
          // 去查询阶段信息
          this.pollingStageInfo() // 开始轮询
          this.deploySuccess = true
          this.loadingInstance.close() // 取消loading
        })
        .catch(() => {
          // 失败
          this.deploySuccess = false
          this.loadingInstance.close() // 取消loading
        })
    },
    /**
     * @description: 初始化数据
     * @return {*}
     */
    initData() {
      if (this.microServices.length === 0) {
        return
      }
      const allStageInfo = {}
      // 初始化默认数据
      for (const microService of this.microServices) {
        allStageInfo[microService.svcId] = getDefaultStageInfo()
      }
      this.allStageInfo = allStageInfo
      // 是否部署过
      const someNotDeploy = this.microServices.some((item) => {
        return item.status === '0' // 存在微服务是初始状态
      })
      if (someNotDeploy) {
        // 有微服务未部署过
        // 去部署
        this.deployMicroServices()
      } else {
        // 全部部署过
        // 直接去查询阶段信息
        this.pollingStageInfo() // 开始轮询
      }
    },
    /**
     * @description: 完成点击
     * @return {*}
     */
    completeClick() {
      // 跳转 策略部署管理
      if (this.$route.path === '/exterior/distributed') {
        this.$message.info('部署完成，请去“策略部署管理”菜单中查看')
        window.location.reload()
      } else {
        this.$router.push({
          name: 'PolicyDeployment'
        })
      }
    },
    /**
     * @description: 已部署回调
     * @return {*}
     */
    distributedCallback() {
      this.$emit('refreshMicroService') // 刷新微服务
    }
  }
}
</script>

<style lang="less" scoped></style>
